﻿using org.xiisoft.game.GobangModule.Chess;
using org.xisoft.game.utils.game;
using org.xisoft.game.utils.game.algorithms;
using System;
using System.Collections.Generic;

namespace org.xisoft.game.GobangModule.Chess.Algorithms
{
    class AiAlgorithm: AlphaBetaAlgorithm<GobangBroad>
    {
        public AiAlgorithm()
        {
            MaxDeep = 4;
        }

        public override MoveAction Search(GobangBroad broad, List<MoveAction> movies, int depth, long alpha, long beta)
        {
            long score = 0;
            int i = 0;
            while (i < movies.Count && movies[i].Score >= 100000)
            {
                score += movies[i].Score;
                i++;
            }

            if(score>0)
            {
                movies[0].Score = score;
                return movies[0];
            }

            return base.Search(broad, movies, depth, alpha, beta);
        }

        public override List<MoveAction> GetAllCanMoves(GobangBroad gobangBroad)
        {
            List<MoveAction> list = new List<MoveAction>();

            for (byte i = 0; i < gobangBroad.MaxX; i++)
                for (byte j = 0; j < gobangBroad.MaxY; j++)
                {
                    if (gobangBroad[i, j] == null)
                    {
                        MoveAction moveAction = new MoveAction { ToX = i, ToY = j };
                        moveAction.Score = GetScore(gobangBroad,i, j);
                        list.Add(moveAction);
                    }
                }

            return list;
        }


        /**
         * 进攻得分
         */ 
        protected long GetOffensiveScore(GobangBroad gobangBroad, int x, int y)
        {
            long score = 0;
            int i;
            Boolean isLink;
            int linkCount = 0;//连着的
            int startBlankCount = 0;//开始空着的
            int endBlankCount= 0;

            int startSameColorCount = 0;//颜色一样的（不连着的）
            int endSameColorCount = 0;

            int leftX = Math.Max(0, x - 5);
            int rightX = Math.Min(gobangBroad.MaxX, x + 5);
            int upY = Math.Max(0, y - 5);
            int downY = Math.Min(gobangBroad.MaxY, y + 5);

            #region 左和右
            startBlankCount = endBlankCount=0;//空着的
            linkCount = 1;//连着的
            startSameColorCount = endSameColorCount= 0;//颜色一样的（不连着的）


            isLink = true;

            i = x - 1;

            while (i >= leftX)
            {
                ChessItem item = gobangBroad[i, y];
                i--;
                if (item == null)
                {
                    startBlankCount++;
                    isLink = false;
                    continue;
                }
                if (item.IsBlack != gobangBroad.IsCurrentBlackMove)
                    break;



                if (isLink)
                    linkCount++;
                else
                    startSameColorCount++;
            }

            i = x + 1;
            isLink = true;

            while (i < rightX)
            {
                ChessItem item = gobangBroad[i, y];
                i++;
                if (item == null)
                {
                    endBlankCount++;
                    isLink = false;
                    continue;
                }
                if (item.IsBlack != gobangBroad.IsCurrentBlackMove)
                    break;

                if (isLink)
                    linkCount++;
                else
                    endSameColorCount++;
            }
            #endregion

            score += GetScore(startBlankCount, endBlankCount, startSameColorCount, endSameColorCount, linkCount);

            #region 上和下
            startBlankCount = endBlankCount = 0;
            startSameColorCount = endSameColorCount = 0;//颜色一样的（不连着的）
            linkCount = 1;//连着的
            isLink = true;
            i = y - 1;
            while (i >= upY)
            {
                ChessItem item = gobangBroad[x, i];
                i--;
                if (item == null)
                {
                    startBlankCount++;
                    isLink = false;
                    continue;
                }
                if (item.IsBlack != gobangBroad.IsCurrentBlackMove)
                    break;

                if (isLink)
                    linkCount++;
                else
                    startSameColorCount++;
            }

            i = y + 1;
            isLink = true;
            while (i < downY)
            {
                ChessItem item = gobangBroad[x, i];
                i++;
                if (item == null)
                {
                    endBlankCount++;
                    isLink = false;
                    continue;
                }
                if (item.IsBlack != gobangBroad.IsCurrentBlackMove)
                    break;


                if (isLink)
                    linkCount++;
                else
                    endSameColorCount++;
            }
            #endregion

            score += GetScore(startBlankCount, endBlankCount, startSameColorCount, endSameColorCount, linkCount);

            int j;
            #region 左上和右下
            startBlankCount = endBlankCount =  0;
            startSameColorCount = endSameColorCount = 0;//颜色一样的（不连着的）
            linkCount = 1;//连着的
            isLink = true;
            i = x - 1;
            j = y - 1;

            while (i >= leftX && j >= upY)
            {
                ChessItem item = gobangBroad[i, j];
                i--;
                j--;
                if (item == null)
                {
                    startBlankCount++;
                    isLink = false;
                    continue;
                }
                if (item.IsBlack != gobangBroad.IsCurrentBlackMove)
                    break;

                if (isLink)
                    linkCount++;
                else
                    startSameColorCount++;
            }

            isLink = true;
            i = x + 1;
            j = y + 1;
            while (i < rightX && j < downY)
            {
                ChessItem item = gobangBroad[i, j];
                i++;
                j++;
                if (item == null)
                {
                    endBlankCount++;
                    isLink = false;
                    continue;
                }
                if (item.IsBlack != gobangBroad.IsCurrentBlackMove)
                    break;


                if (isLink)
                    linkCount++;
                else
                    endSameColorCount++;
            }
            #endregion

            score += GetScore(startBlankCount, endBlankCount, startSameColorCount, endSameColorCount, linkCount);

            #region 右上和左下
            startBlankCount = endBlankCount =  0;
            startSameColorCount = endSameColorCount = 0;//颜色一样的（不连着的）
            linkCount = 1;//连着的
            isLink = true;
            i = x - 1;
            j = y + 1;
            while (i >= leftX && j < downY)
            {
                ChessItem item = gobangBroad[i, j];
                i--;
                j++;
                if (item == null)
                {
                    startBlankCount++;
                    isLink = false;
                    continue;
                }
                if (item.IsBlack != gobangBroad.IsCurrentBlackMove)
                    break;

                if (isLink)
                    linkCount++;
                else
                    startSameColorCount++;
            }

            isLink = true;
            i = x + 1;
            j = y - 1;
            while (i < rightX && j >= upY)
            {
                ChessItem item = gobangBroad[i, j];
                i++;
                j--;
                if (item == null)
                {
                    isLink = false;
                    endBlankCount++;
                    continue;
                }
                if (item.IsBlack != gobangBroad.IsCurrentBlackMove)
                    break;

                if (isLink)
                    linkCount++;
                else
                    endSameColorCount++;
            }
            #endregion

            score += GetScore(startBlankCount, endBlankCount, startSameColorCount, endSameColorCount, linkCount);

            return score;
        }


        public override bool? GetWinColor(GobangBroad gobangBroad)
        {
            bool[,] visited = new bool [gobangBroad.MaxX, gobangBroad.MaxY];
            for (int x = 0; x < gobangBroad.MaxX; x++)
                for(int y = 0;y < gobangBroad.MaxY;y++)
                {
                    if (visited[x, y]) continue;

                    ChessItem currentItem = gobangBroad[x, y];
                    
                    if (currentItem != null)
                    {
                        visited[x, y] = true;
                        int i;
                        int linkCount;

                        int leftX = Math.Max(0, x - 4);
                        int rightX = Math.Min(gobangBroad.MaxX, x + 5);
                        int upY = Math.Max(0, y - 4);
                        int downY = Math.Min(gobangBroad.MaxY, y + 5);

                        #region 左和右

                        linkCount = 1;//连着的

                        i = x - 1;

                        while (i >= leftX)
                        {
                            ChessItem item = gobangBroad[i, y];
                            
                            
                            if (item == null)
                                break;
                            if (item.IsBlack != currentItem.IsBlack)
                                break;

                            visited[i, y] = true;
                            linkCount++;
                            i--;
                        }

                        i = x + 1;

                        while (i < rightX)
                        {
                            ChessItem item = gobangBroad[i, y];
                            
                            
                            if (item == null)
                                break;
                            if (item.IsBlack != currentItem.IsBlack)
                                break;

                            visited[i, y] = true;
                            linkCount++;
                            i++;
                        }
                        #endregion

 
                        if (linkCount >= 5)
                            return currentItem.IsBlack;

                        #region 上和下

                        linkCount = 1;//连着的
                        i = y - 1;
                        while (i >= upY)
                        {
                            ChessItem item = gobangBroad[x, i];
                            
                            
                            if (item == null)
                                break;
                            if (item.IsBlack != currentItem.IsBlack)
                                break;

                            visited[x, i] = true;
                            linkCount++;
                            i--;
                        }

                        i = y + 1;
                        while (i < downY)
                        {
                            ChessItem item = gobangBroad[x, i];
                            
                            
                            if (item == null)
                                break;
                            if (item.IsBlack != currentItem.IsBlack)
                                break;
                            visited[x, i] = true;
                            linkCount++;
                            i++;
                        }
                        #endregion


                        if (linkCount >= 5)
                            return currentItem.IsBlack;

                        int j;
                        #region 左上和右下

                        linkCount = 1;//连着的
     
                        i = x - 1;
                        j = y - 1;

                        while (i >= leftX && j >= upY)
                        {
                            ChessItem item = gobangBroad[i, j];
                            
               
                            if (item == null)
                                break;
                            if (item.IsBlack != currentItem.IsBlack)
                                break;

                            visited[i, j] = true;
                            linkCount++;
                            i--;
                            j--;
                        }


                        i = x + 1;
                        j = y + 1;
                        while (i < rightX && j < downY)
                        {
                            ChessItem item = gobangBroad[i, j];
                            
                           
                            if (item == null)
                                break;
                            if (item.IsBlack != currentItem.IsBlack)
                                break;

                            visited[i, j] = true;
                            linkCount++;
                            i++;
                            j++;
                        }
                        #endregion

 
                        if (linkCount >= 5)
                            return currentItem.IsBlack;
                        #region 右上和左下

                        linkCount = 1;//连着的

                        i = x - 1;
                        j = y + 1;
                        while (i >= leftX && j < downY)
                        {
                            ChessItem item = gobangBroad[i, j];
                            
                   
                            if (item == null)
                                break;
                            if (item.IsBlack != currentItem.IsBlack)
                                break;

                            visited[i, j] = true;
                            linkCount++;
                            i--;
                            j++;
                        }


                        i = x + 1;
                        j = y - 1;
                        while (i < rightX && j >= upY)
                        {
                            ChessItem item = gobangBroad[i, j];
                            
                   
                            if (item == null)
                                break;
                            if (item.IsBlack != currentItem.IsBlack)
                                break;

                            visited[i, j] = true;
                            linkCount++;
                            i++;
                            j--;
                        }
                        #endregion
                        if (linkCount >= 5)
                            return currentItem.IsBlack;
                    }
                }
            return null;
        }

        protected long GetScore(GobangBroad gobangBroad, int x, int y)
        {
            return ScoreHelper.GetPositionScore(x,y)+ GetOffensiveScore(gobangBroad, x, y)+GetDefenseScore(gobangBroad,x,y);
        }

        /**
         * 防御得分
         */ 
        private long GetDefenseScore(GobangBroad gobangBroad, int x, int y)
        {

                long score = 0;
                int i;
                int linkCount = 0;//连着的
                bool blockStart;
                bool blockEnd;

                int leftX = Math.Max(0, x - 4);
                int rightX = Math.Min(gobangBroad.MaxX, x + 5);
                int upY = Math.Max(0, y - 4);
                int downY = Math.Min(gobangBroad.MaxY, y + 5);

                #region 左和右
                linkCount = 0;//连着的
                i = x - 1;
                blockStart = blockEnd = false;

                while (i >= leftX)
                {
                    ChessItem item = gobangBroad[i, y];
                    i--;
                    if (item == null)
                        break;

                    if (item.IsBlack == gobangBroad.IsCurrentBlackMove)
                    {
                        blockStart = true;
                        break;
                    }

                    linkCount++;

                }

                i = x + 1;

                while (i < rightX)
                {
                    ChessItem item = gobangBroad[i, y];
                    i++;
                    if (item == null)
                        break;

                    if (item.IsBlack == gobangBroad.IsCurrentBlackMove)
                    {
                        blockEnd = true;
                        break;
                    }


                    linkCount++;

                }

                if (linkCount >= 4)
                    score += 10000;
                else if (!blockStart && !blockEnd)
                    score += 200;
                else
                    score += 50;
                #endregion


                #region 上和下
                linkCount = 0;
                blockStart = blockEnd = false;

                i = y - 1;
                while (i >= upY)
                {
                    ChessItem item = gobangBroad[x, i];
                    i--;
                    if (item == null)
                        break;

                    if (item.IsBlack == gobangBroad.IsCurrentBlackMove)
                    {
                        blockStart = true;
                        break;
                    }
                    linkCount++;

                }


                i = y + 1;
                while (i < downY)
                {
                    ChessItem item = gobangBroad[x, i];
                    i++;
                    if (item == null)
                        break;

                    if (item.IsBlack == gobangBroad.IsCurrentBlackMove)
                    {
                        blockEnd = true;
                        break;
                    }



                    linkCount++;

                }

                if (linkCount >= 4)
                    score += 10000;
                else if (!blockStart && !blockEnd)
                    score += 200;
                else
                    score += 50;
                #endregion

                int j;
                #region 左上和右下
                blockStart = blockEnd = false;
                linkCount = 0;//连着的
                i = x - 1;
                j = y - 1;

                while (i >= leftX && j >= upY)
                {
                    ChessItem item = gobangBroad[i, j];
                    i--;
                    j--;
                    if (item == null)
                        break;

                    if (item.IsBlack == gobangBroad.IsCurrentBlackMove)
                    {
                        blockStart = true;
                        break;
                    }

                    linkCount++;

                }


                i = x + 1;
                j = y + 1;
                while (i < rightX && j < downY)
                {
                    ChessItem item = gobangBroad[i, j];
                    i++;
                    j++;
                    if (item == null)
                        break;

                    if (item.IsBlack == gobangBroad.IsCurrentBlackMove)
                    {
                        blockEnd = true;
                        break;
                    }


                    linkCount++;

                }

                if (linkCount >= 4)
                    score += 10000;
                else if (!blockStart && !blockEnd)
                    score += 200;
                else
                    score += 50;
                #endregion


                #region 右上和左下
                blockStart = blockEnd = false;
                linkCount = 0;//连着的
                i = x - 1;
                j = y + 1;
                while (i >= leftX && j < downY)
                {
                    ChessItem item = gobangBroad[i, j];
                    i--;
                    j++;
                    if (item == null)
                        break;

                    if (item.IsBlack == gobangBroad.IsCurrentBlackMove)
                    {
                        blockStart = true;
                        break;
                    }


                    linkCount++;

                }


                i = x + 1;
                j = y - 1;
                while (i < rightX && j >= upY)
                {
                    ChessItem item = gobangBroad[i, j];
                    i++;
                    j--;
                    if (item == null)
                        break;

                    if (item.IsBlack == gobangBroad.IsCurrentBlackMove)
                    {
                        blockEnd = true;
                        break;
                    }


                    linkCount++;

                }

                if (linkCount >= 4)
                    score += 10000;
                else if (!blockStart && !blockEnd)
                    score += 200;
                else
                    score += 50;
                #endregion


                return score;
            
        }


        private long GetScore(int startBlankCount,int endBlankCount,int startSameColorCount,int endSameColorCount, int linkCount)
        {
            //只连 11111
            if (linkCount >= 5)
                return 100000;


            if (linkCount == 4)
            {
                //活四 011110
                if (startBlankCount > 0 && endBlankCount > 0)
                    return 10000;

                //冲四 011112  211110
                if (startBlankCount > 0 || endBlankCount > 0)
                    return 10000;

                //死四 211112
                return -5;
            }

            //111
            if(linkCount == 3 )
            {
                //冲四 10111 11101
                if (startSameColorCount > 0 || endSameColorCount > 0)
                    return 10000;

                //活三01110
                if (startBlankCount > 0 && endBlankCount > 0)
                    return 200;

                //眠三001112  211100
                if (startBlankCount > 1 || endBlankCount > 1)
                    return 50;

                //201112  211102
                //if (startBlankCount > 0 || endBlankCount > 0)
                //    return 0;

                //死三21112
                return -5;
            }

            //11
            if(linkCount == 2)
            {
                //冲四 0110110 1010110 0110101
                if ((startSameColorCount > 1 && startBlankCount >1 && endBlankCount>0) || (endSameColorCount > 1 && endBlankCount>1 && startBlankCount>0))
                    return 1000;

                //1011
                if (startSameColorCount > 0)
                {
                    //11011  101011
                    if(startSameColorCount > 1)
                    {
                        //101011 011011
                        if (startBlankCount > 1)
                            return 1000;
                    }


                    //101101
                    if(endSameColorCount > 0)
                    {
                        //活三 1011010
                        if (endBlankCount > 1)
                            return 200;
                        //眠三 011012
                        return 50;
                    }



                    // 眠三01011
                    if (startBlankCount > 1)
                    {
                        //活三 010110
                        if (endBlankCount > 0)
                            return 200;
                        //眠三 010112
                        return 50;
                    }
                    //眠三 210110
                    if (endBlankCount > 0)
                        return 50;


                    //眠三01011

                        return 50;
                }



                // 21101
                if (endSameColorCount>0 )
                {
                    //眠三 211010
                    if (endBlankCount > 1)
                        return 50;

                    //211012
                    return 0;
                }

                //死二 2112
                return -5;
            }

            if(linkCount == 1)
            {
                //冲四11101 10111
                if (startSameColorCount > 3 || endSameColorCount>3)
                    return 10000;

                //眠三0110c  1010c c010 c0110
                if ((startSameColorCount > 2 && startBlankCount>2) || (endSameColorCount > 2 && endBlankCount>2))
                    return 50;

                //眠三110c0
                if (startSameColorCount > 2 && endBlankCount > 0 || endSameColorCount>2 && startBlankCount>0)
                    return 50;

                //眠三10c01
                if (startSameColorCount > 1 && endSameColorCount > 1)
                    return 50;

            }

            /*眠三50
010112
10011
10101
2011102

活二5
00110
01010
010010

眠二3
000112
211000
001012
010012
10001
2010102
2011002
*/

            return 0;
        }

    }
}
